package ray;

import ray.mgocc.*;
import ray.mgocc.net.*;
import ray.mgocc.parser.*;
import ray.mgocc.title.*;
import java.util.*;
import java.io.*;
import org.xml.sax.InputSource;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class App{
    private final static boolean NET = true;
    private final static boolean FORCE = true;
    private final static Log log = LogFactory.getLog(App.class);
    private PlayerCharacter pc = null;
    private Store local = null;
    private Agent agent = null;
    private TitleList titles = null;
    public static void main( String[] args ){
        log.info("app start."+Arrays.asList(args));
        App app = new App();
        if(1 == args.length){
            app.setPlayerCharacter(new PlayerCharacter(Integer.parseInt(args[0])));
        }
        app.init();
        Record record = app.parse();
        for(Title title:app.getTitles()){
            System.out.println(title.details());
        }
        List<Map.Entry> names = new ArrayList<Map.Entry>(record.getAll().entrySet());
        Comparator compare = new Comparator<Map.Entry>(){
            public int compare(Map.Entry o1,Map.Entry o2){
                return o1.getKey().toString().compareTo(o2.getKey().toString());
            }
        };
        Collections.sort(names,compare);
        for(Map.Entry entry:names){
//             System.out.println(entry.getKey().toString()+":"+entry.getValue().toString());
        }

    }
    private String getName(){
        return "mgocc";
    }
    public List<Title> getTitles(){
        return this.titles;
    }
    private Time getPlayTime(File dir){
        File file = new File(dir,"record0_0.html");
        Source source = new StoredSource(file);
        Time time = getPlayTime(source);
        return time;
    }
    private Time getPlayTime(Source source){
        HtmlParser checker = new HtmlParser();
        Score total = checker.parse(source);
        Time time = total.getTime("PLAY TIME");
        return time;
    }
    /**
     * @return true:updateが必要。
     */
    private boolean check(RecordPage record){
        Time current = getPlayTime(record.get(RecordPage.TOTAL,RecordPage.TAB_TOTAL));

        Time before = null;
        File dir = local.getBefore();
        if(null!=dir){
            before = getPlayTime(dir);
        }

        log.info(current.equals(before)+":"+before+" == "+current);
        boolean update = !current.equals(before);
        return update;
    }
    public void init(){
        local = Store.getInstance();
        agent = new Agent();
        agent.setStore(local);
        
        boolean login = false;
        if(null==pc){
            agent.setStore(local);
            pc = login();
            login = true;
        }
        local.setPlayerCharacter(pc);
        if(FORCE||NET&&local.needUpdate()){
            if(!login){
                login();
            }
            RecordPage record = new RecordPage(agent,this.pc);
            if(check(record) && false){
                // 最新と比較して更新がある。
                try{
                    record.getAll();
                }catch(RuntimeException e){
                    log.error("failed record get.",e);
                    local.clean();
                    throw e;
                }
            }else{
                log.info("not updated.");
                local.clean();
                local = local.getLatest();
            }
        }else{
            local = local.getLatest();
        }
        log.info(local.getDir().toURI());

        //ray.net.PlayerSelectPage psp = new ray.net.PlayerSelectPage();
        //System.out.println(psp.getPlayerCharacters().toString());
        //new ray.net.GameAccount();

    }
    PlayerCharacter login(){
        GameAccount account = new GameAccount();
        account.save();
        CommunitySupportPage site = new CommunitySupportPage(agent,account);
        PlayerCharacter me = site.select();

        log.info("login="+me);
        return me;
    }
    public Record parse(){
        Record record = new Record();
        try{
            Store store = this.local;
            log.info("parse from "+store.getDir());
            HtmlParser parser = new HtmlParser();
            FileReader in;
            Writer out = new StringWriter();
            for(File file:store.getDir().listFiles()){
                in = new FileReader(file);
                Score score = parser.parse(in);
                log.debug("put score:"+score.getName());
                record.add(score);
                in.close();
            }

            //log.info(record);

            titles = new TitleList();
            titles.setRecord(record);
            for(Title title:titles){
                log.info(title.details());
            }

            Score score;
            score = record.getTotal("Total");
            log.info(score.getRule().toString());
            score = record.getWeek("Total");
            log.info(score.getRule().toString());

            log.info(titles.getList());
            log.info(titles.getTitle());
            
            String key = "WEEK.Total.PLAY TIME";
            log.info(key+"="+record.getValue(key));
            key = "WEEK.Total.ALL.KILLS";
            log.info(key+"="+record.getValue(key));

            log.info(titles.getTitle("Rat").getParam().toString());
        }catch(IOException e){
            log.error("parse error.",e);
        }
        return record;
    }
    void setPlayerCharacter(final PlayerCharacter pc){
        this.pc = pc;
    }
}
